home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Technotools
/
Technotools (Chestnut CD-ROM)(1993).ISO
/
lang_c
/
serialtc
/
serial.c
next >
Wrap
Text File
|
1988-02-19
|
6KB
|
243 lines
/*
==========================
c.language/listings #115, from barryn, 8544 chars, Sat Aug 29 17:17:28 1987
--------------------------
TITLE: Communications routines in Turbo C
The following code shows how to take advantage of some of
the TurboC extensions to the C language to do asynchronous
communications (without having to write supporting assembly-
language routines). The code was supplied by Peter Ibbotson of
Borland. After the communications-related functions themselves,
you'll find a small main() section of code that uses those functions
to implement a rudimentary glass-TTY terminal program. (I say
rudimentary to mean that control characters are not recognized and
there are no file transfer, dialing directory, etc. features.)
First, here's Serial.C:
*/
/* SERIAL.C */
#include "serial.h"
#include <dos.h>
#include <stdio.h>
#include <conio.h>
#include <bios.h>
#include <process.h>
int SError;
int portbase=0;
void interrupt (*oldvects[2])();
char ccbuf[SBUFSIZ];
int startbuf=0;
int endbuf=0;
/* this does the hard work (handling interrupts) */
void interrupt com_int (void)
{ disable ();
if ((inportb (portbase+IIR) & RX_MASK)==RX_ID)
{ if (((endbuf+1) & 0x1fff)==startbuf)
SError=BUFOVFL;
ccbuf[endbuf++]=inportb (portbase+RX);
endbuf&=0x1fff;
};
outportb (ICR,EOI);
enable ();
}
/* this routine returns the currently value in the buffer */
int getccb(void)
{ int res;
if (endbuf==startbuf) return (-1);
res=(int) ccbuf[startbuf];
startbuf=(startbuf+1) % SBUFSIZ;
return (res);
}
void setvects (void)
{ oldvects[0]=getvect(0x0b);
oldvects[1]=getvect(0x0c);
setvect(0x0b,com_int);
setvect(0x0c,com_int);
}
void resvects (void)
{ setvect(0x0b,oldvects[0]);
setvect(0x0c,oldvects[1]);
}
void i_enable (int pnum)
{ int c;
disable();
c = inportb (portbase+MCR) | MC_INT;
outportb (portbase+MCR,c);
outportb (portbase+IER,RX_INT);
c = inportb (IMR) & (pnum==2 ? IRQ3 : IRQ4);
outportb (IMR,c);
enable();
}
void i_disable (void)
{ int c;
disable ();
c=inportb (IMR) | ~IRQ3 | ~IRQ4;
outportb (IMR,c);
outportb (portbase + IER,0);
c=inportb (portbase+MCR) & ~MC_INT;
outportb (portbase+MCR,c);
enable ();
}
void comon (void)
{ int c,pnum;
pnum = portbase == COM1BASE ? 1 : 2;
i_enable (pnum);
c=inportb (portbase + MCR) | DTR | RTS;
outportb (portbase + MCR,c);
}
void initserial (void)
{ endbuf=startbuf=0;
setvects();
comon();
};
void comoff (void)
{ i_disable ();
outportb (portbase+MCR,0);
}
void closeserial(void)
{ comoff();
resvects();
};
/* this outputs a serial character */
int SerialOut (char x)
{ long timeout = 0x0000ffff;
outportb (portbase+MCR,OUT2|DTR|RTS);
/* wait for clear to send */
while ((inportb(portbase + MSR) & CTS)==0)
if ((--timeout)==0) return (-1);
timeout=0x0000ffff;
/* wait for outport register to clear */
while ((inportb(portbase+LSR) & DSR)==0)
if ((--timeout)==0) return (-1);
disable ();
outportb (portbase+TX,x);
enable ();
return (0);
}
/* this routine sets which port we are working with */
int SetPort (int Port)
{ int far * RS232_Addr;
int Offset;
switch (Port) /* sort out the base address */
{ case 1 : Offset=0x0000; break; /* only ports one & two allowed */
case 2 : Offset=0x0002; break;
default : return (-1);
};
RS232_Addr=MK_FP(0x0040,Offset); /* find out where the port is */
if (*RS232_Addr==0) return (-1); /* if it ain't there return (-1)*/
portbase=*RS232_Addr; /* otherwise set portbase */
return (0);
}
/* this routine sets the speed; will accept funny baud rates */
int SetSpeed (int Speed)
{ char c;
int divisor;
if (Speed==0) return (-1); /* avoid divide by zero */
else divisor=(int)(115200L/Speed);
if (portbase==0) return (-11);
disable ();
c=inportb (portbase+LCR);
outportb (portbase+LCR,(c|0x80)); /* set DLAB */
outportb (portbase+DLL,(divisor & 0x00ff)); /* set divisor */
outportb (portbase+DLH,((divisor>>8)&0x00ff));
outportb (portbase+LCR,c);
enable();
return (0);
}
/* This routine set the LCR */
int SetOthers (int Parity,int Bits,int StopBit)
{ int temp;
if (portbase==0) return (-1);
if ((Parity<NO_PAR) || (Parity>OD_PAR)) return (-1);
if ((Bits<5) || (Bits>8)) return (-1);
if ((StopBit<1) || (StopBit>2)) return (-1);
temp=Bits-5;
temp|=((StopBit==1) ? 0x00 : 0x04);
switch (Parity)
{ case NO_PAR : temp |= 0x00; break;
case OD_PAR : temp |= 0x08; break;
case EV_PAR : temp |= 0x18; break;
}
disable(); /* turn off interrupts */
outportb (portbase+LCR,temp);
enable(); /* turn em back on */
return (0);
}
/* This routine sets the ports */
int setserial (int Port,int Speed,int Parity,int Bits,int StopBit)
{ if (SetPort(Port)==-1) return(-1);
if (SetSpeed(Speed)==-1) return(-1);
if (SetOthers(Parity,Bits,StopBit)==-1) return (-1);
return (0);
}
/* short demo */
/* this opens the ports and echos to screen until */
/* ESCape received */
main ()
{ int c;
if (setserial (COM1,2400,NO_PAR,8,1) ==-1) exit (1);
initserial();
printf("You're now in terminal mode. Press ESC to quit the program.\n\n");
do {
if (kbhit()) {
c = getch();
if (c==27)
break;
SerialOut(c);
}
if ((c=getccb())!=-1)
putchar (c);
} while (c!=27);
closeserial();
}